// let p1 = new Promise((resolve, reject) => {
//   resolve('ok')
//   throw('报错')
// })
// console.log(p1);


// resolve()  Promise的状态会变成fulfilled
// reject()  Promise的状态会变成rejected
// Promise的状态只能变更一次
// throw() 相当于 reject()

// let p1 = new Promise((resolve, reject) => {
//   resolve('成功');
//   reject('失败');
//   throw('报错');  //相当于reject()
// })

// console.log(p1);

// 1. 调用resolve() Promise的状态会变成fulfilled
// 2. 调用reject() Promise的状态会变成rejected
// 3. Promsie的状态只变更一次
// 4. throw()相当于reject()

class MyPromise {
	constructor(executor) {
		this.status = 'pending';
		this.value = null;
		this.onFulfilledCallbacks = []; // 用来保存成功的回调(处理异步)
		this.onRejectedCallbacks = []; // 用来保存失败的回调(处理异步)
		try {
			executor(this.resolve.bind(this), this.reject.bind(this));
		} catch (error) {
			this.reject(error)
		}
	}

	resolve(value) {
		if (this.status !== 'pending') return;
		this.status = 'fulfilled';
		this.value = value;
		// 调用then里面的回调
		while (this.onFulfilledCallbacks.length) {
			this.onFulfilledCallbacks.shift()(this.value)
		}
	}

	reject(reason) {
		if (this.status !== 'pending') return
		this.status = 'rejected';
		this.value = reason;
		while (this.onRejectedCallbacks.length) {
			this.onRejectedCallbacks.shift()(this.value)
		}
	}

	then(onFulfilled, onRejected) {
		onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
		onRejected = typeof onRejected === 'function' ? onRejected : val => {
			throw val
		}

		var thenPromise = new MyPromise((resolve, reject) => {

			const resolvePromise = callback => {
				setTimeout(() => { // 让整个回调函数比同步代码晚一点执行，官方不是使用setTimeout实现
					try {
						const x = callback(this.value);
						if (x === thenPromise) { // 你正在返回自身
							throw new Error('不允许返回自身！');
						}
						if (x instanceof MyPromise) { // 返回的是一个Promise对象
							x.then(resolve, reject);
						} else { // 直接返回一个值，作为resolve的值，传递给下一个.then
							resolve(x);
						}
					} catch (error) {
						reject(error);
						// throw new Error(error)
					}
				})
			}

			if (this.status === 'fulfilled') {
				resolvePromise(onFulfilled)
			} else if (this.status === 'rejected') {
				resolvePromise(onRejected)
			} else if (this.status === 'pending') {
				this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled));
				this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected));
			}
		})
		return thenPromise
	}

	static all(promises) { // 静态方法只能被构造函数调用
		let result = [];
		let count = 0;
		return new MyPromise((resolve, reject) => {
			const addResolve = (val, index) => {
				result[index] = val;
				count++;
				if (count === promises.length) {
					return resolve(result)
				}
			}

			promises.forEach((promise, index) => {
				if (promise instanceof MyPromise) {
					promise.then(
						res => {
							addResolve(res, index)
						},
						err => {
							return reject(err);
						}
					)
				} else {
					addResolve(promise, index)
				}
			})

		})
	}

	static race(promises) {
		return new MyPromise((resolve, reject) => {
			promises.forEach((promise, index) => {
				if (promise instanceof MyPromise) {
					promise.then(res => {
						return resolve(res)
					}, err => {
						reject(err)
					})
				} else {
					return resolve(promise)
				}
			})
		})
	}

	static any(promises) {
		let count = 0
		return new MyPromise((resolve, reject) => {
			promises.forEach((promise, index) => {
				if (promise instanceof MyPromise) {
					promise.then(res => {
						resolve(res)
					}, err => {
						count++
						if (count === promises.length) {
							reject(new AggregateError('All promises were rejected'))
						}
					})
				} else {
					return resolve(promise)
				}
			})
		})
	}

	static allSettled(promises) {
		let result = []
		let count = 0
		return new MyPromise((resolve, reject) => {
			const addData = (status, res, index) => {
				let key = null
				key = status == 'fullfilled' ? 'value' : 'reason'
				result[index] = {
					status,
					[key]: res
				}
				count++
				if (count === promises.length) {
					resolve(result)
				}
			}
			promises.forEach((promise, index) => {
				if (promise instanceof MyPromise) {
					promise.then(res => {
						addData('fullfilled', res, index)
					}, err => {
						addData('rejected', err, index)
					})
				} else {
					addData('fullfilled', promise, index)
				}
			})
		})
	}
}


// let p1 = new MyPromise((resolve, reject) => {
//   // setTimeout(() =>{
//   //   resolve(100)
//   // },1000)
//   // resolve(100);
//   reject('err')
// })
// p1.then(
//   res => 2 * res,
//   err => console.log(err)
// ).then(
//   res => console.log(res),
//   err => console.log(err)
// )

// console.log(123);
// console.log(p1);

// 1. 基本实现
// 2. promise定时器
// 3. 链式调用
// 4. 微任务处理


const p1 = new MyPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok1')
	}, 2000)
})
const p2 = new MyPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok2')
	}, 1000)
})
const p3 = new MyPromise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok3')
	}, 500)
})
const p4 = new MyPromise((resolve, reject) => {
	setTimeout(() => {
		reject('error')
	}, 500)
})
const p5 = function() {}

const p6 = function() {
	setTimeout(() => {
		console.log('success');
	})
}

MyPromise.all([p1, p2, p3, p4])
	.then(
		res => {
			console.log(res);
			p4()
		},
		err => {
			console.log(err);
		}
	)
MyPromise.race([p1, p2, p3, p4])
	.then(
		res => {
			console.log(res);
			p4()
		},
		err => {
			console.log(err);
		}
	)
MyPromise.allSettled([p1, p2, p3, p4])
	.then(
		res => {
			console.log(res);
			p4()
		},
		err => {
			console.log(err);
		}
	)
